-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[SandboxVec][BottomUpVec] Clean up dead instructions #115267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-vectorizers @llvm/pr-subscribers-llvm-transforms Author: vporpo (vporpo) ChangesWhen scalars get replaced by vectors the original scalars may become dead. In that case erase them. Full diff: https://github.com/llvm/llvm-project/pull/115267.diff 3 Files Affected:
diff --git a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
index 18e34bcec81b06..af27477f2ce303 100644
--- a/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
+++ b/llvm/include/llvm/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.h
@@ -25,10 +25,12 @@ namespace llvm::sandboxir {
class BottomUpVec final : public FunctionPass {
bool Change = false;
std::unique_ptr<LegalityAnalysis> Legality;
+ DenseSet<Instruction *> DeadInstrCandidates;
/// Creates and returns a vector instruction that replaces the instructions in
/// \p Bndl. \p Operands are the already vectorized operands.
Value *createVectorInstr(ArrayRef<Value *> Bndl, ArrayRef<Value *> Operands);
+ void tryEraseDeadInstrs();
Value *vectorizeRec(ArrayRef<Value *> Bndl);
bool tryVectorize(ArrayRef<Value *> Seeds);
diff --git a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
index 0a930d30aeab58..ac2565816ff7d1 100644
--- a/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
+++ b/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Passes/BottomUpVec.cpp
@@ -153,6 +153,20 @@ Value *BottomUpVec::createVectorInstr(ArrayRef<Value *> Bndl,
// TODO: Propagate debug info.
}
+void BottomUpVec::tryEraseDeadInstrs() {
+ bool Change = true;
+ while (Change) {
+ Change = false;
+ for (Instruction *I : make_early_inc_range(DeadInstrCandidates)) {
+ if (I->hasNUses(0)) {
+ Change = true;
+ I->eraseFromParent();
+ DeadInstrCandidates.erase(I);
+ }
+ }
+ }
+}
+
Value *BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
Value *NewVec = nullptr;
const auto &LegalityRes = Legality->canVectorize(Bndl);
@@ -182,7 +196,11 @@ Value *BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
}
NewVec = createVectorInstr(Bndl, VecOperands);
- // TODO: Collect potentially dead instructions.
+ // Collect the original scalar instructions as they may be dead.
+ if (NewVec != nullptr) {
+ for (Value *V : Bndl)
+ DeadInstrCandidates.insert(cast<Instruction>(V));
+ }
break;
}
case LegalityResultID::Pack: {
@@ -194,7 +212,9 @@ Value *BottomUpVec::vectorizeRec(ArrayRef<Value *> Bndl) {
}
bool BottomUpVec::tryVectorize(ArrayRef<Value *> Bndl) {
+ DeadInstrCandidates.clear();
vectorizeRec(Bndl);
+ tryEraseDeadInstrs();
return Change;
}
diff --git a/llvm/test/Transforms/SandboxVectorizer/bottomup_basic.ll b/llvm/test/Transforms/SandboxVectorizer/bottomup_basic.ll
index e56dbd75963f7a..4f8d821c7ed581 100644
--- a/llvm/test/Transforms/SandboxVectorizer/bottomup_basic.ll
+++ b/llvm/test/Transforms/SandboxVectorizer/bottomup_basic.ll
@@ -6,11 +6,7 @@ define void @store_load(ptr %ptr) {
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
-; CHECK-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
-; CHECK-NEXT: store float [[LD0]], ptr [[PTR0]], align 4
-; CHECK-NEXT: store float [[LD1]], ptr [[PTR1]], align 4
; CHECK-NEXT: store <2 x float> [[VECL]], ptr [[PTR0]], align 4
; CHECK-NEXT: ret void
;
@@ -31,14 +27,8 @@ define void @store_fpext_load(ptr %ptr) {
; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
; CHECK-NEXT: [[PTRD0:%.*]] = getelementptr double, ptr [[PTR]], i32 0
; CHECK-NEXT: [[PTRD1:%.*]] = getelementptr double, ptr [[PTR]], i32 1
-; CHECK-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[FPEXT0:%.*]] = fpext float [[LD0]] to double
-; CHECK-NEXT: [[FPEXT1:%.*]] = fpext float [[LD1]] to double
; CHECK-NEXT: [[VCAST:%.*]] = fpext <2 x float> [[VECL]] to <2 x double>
-; CHECK-NEXT: store double [[FPEXT0]], ptr [[PTRD0]], align 8
-; CHECK-NEXT: store double [[FPEXT1]], ptr [[PTRD1]], align 8
; CHECK-NEXT: store <2 x double> [[VCAST]], ptr [[PTRD0]], align 8
; CHECK-NEXT: ret void
;
@@ -62,20 +52,10 @@ define void @store_fcmp_zext_load(ptr %ptr) {
; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
; CHECK-NEXT: [[PTRB0:%.*]] = getelementptr i32, ptr [[PTR]], i32 0
; CHECK-NEXT: [[PTRB1:%.*]] = getelementptr i32, ptr [[PTR]], i32 1
-; CHECK-NEXT: [[LDB0:%.*]] = load float, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LDB1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT: [[VECL1:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LDA0:%.*]] = load float, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LDA1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[FCMP0:%.*]] = fcmp ogt float [[LDA0]], [[LDB0]]
-; CHECK-NEXT: [[FCMP1:%.*]] = fcmp ogt float [[LDA1]], [[LDB1]]
; CHECK-NEXT: [[VCMP:%.*]] = fcmp ogt <2 x float> [[VECL]], [[VECL1]]
-; CHECK-NEXT: [[ZEXT0:%.*]] = zext i1 [[FCMP0]] to i32
-; CHECK-NEXT: [[ZEXT1:%.*]] = zext i1 [[FCMP1]] to i32
; CHECK-NEXT: [[VCAST:%.*]] = zext <2 x i1> [[VCMP]] to <2 x i32>
-; CHECK-NEXT: store i32 [[ZEXT0]], ptr [[PTRB0]], align 4
-; CHECK-NEXT: store i32 [[ZEXT1]], ptr [[PTRB1]], align 4
; CHECK-NEXT: store <2 x i32> [[VCAST]], ptr [[PTRB0]], align 4
; CHECK-NEXT: ret void
;
@@ -101,17 +81,9 @@ define void @store_fadd_load(ptr %ptr) {
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
-; CHECK-NEXT: [[LDA0:%.*]] = load float, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LDA1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LDB0:%.*]] = load float, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LDB1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT: [[VECL1:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[FADD0:%.*]] = fadd float [[LDA0]], [[LDB0]]
-; CHECK-NEXT: [[FADD1:%.*]] = fadd float [[LDA1]], [[LDB1]]
; CHECK-NEXT: [[VEC:%.*]] = fadd <2 x float> [[VECL]], [[VECL1]]
-; CHECK-NEXT: store float [[FADD0]], ptr [[PTR0]], align 4
-; CHECK-NEXT: store float [[FADD1]], ptr [[PTR1]], align 4
; CHECK-NEXT: store <2 x float> [[VEC]], ptr [[PTR0]], align 4
; CHECK-NEXT: ret void
;
@@ -133,14 +105,8 @@ define void @store_fneg_load(ptr %ptr) {
; CHECK-SAME: ptr [[PTR:%.*]]) {
; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
-; CHECK-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4
; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
-; CHECK-NEXT: [[FNEG0:%.*]] = fneg float [[LD0]]
-; CHECK-NEXT: [[FNEG1:%.*]] = fneg float [[LD1]]
; CHECK-NEXT: [[VEC:%.*]] = fneg <2 x float> [[VECL]]
-; CHECK-NEXT: store float [[FNEG0]], ptr [[PTR0]], align 4
-; CHECK-NEXT: store float [[FNEG1]], ptr [[PTR1]], align 4
; CHECK-NEXT: store <2 x float> [[VEC]], ptr [[PTR0]], align 4
; CHECK-NEXT: ret void
;
@@ -155,3 +121,25 @@ define void @store_fneg_load(ptr %ptr) {
ret void
}
+define float @sclars_with_external_uses_not_dead(ptr %ptr) {
+; CHECK-LABEL: define float @sclars_with_external_uses_not_dead(
+; CHECK-SAME: ptr [[PTR:%.*]]) {
+; CHECK-NEXT: [[PTR0:%.*]] = getelementptr float, ptr [[PTR]], i32 0
+; CHECK-NEXT: [[PTR1:%.*]] = getelementptr float, ptr [[PTR]], i32 1
+; CHECK-NEXT: [[LD0:%.*]] = load float, ptr [[PTR0]], align 4
+; CHECK-NEXT: [[LD1:%.*]] = load float, ptr [[PTR1]], align 4
+; CHECK-NEXT: [[VECL:%.*]] = load <2 x float>, ptr [[PTR0]], align 4
+; CHECK-NEXT: store <2 x float> [[VECL]], ptr [[PTR0]], align 4
+; CHECK-NEXT: [[USER:%.*]] = fneg float [[LD1]]
+; CHECK-NEXT: ret float [[LD0]]
+;
+ %ptr0 = getelementptr float, ptr %ptr, i32 0
+ %ptr1 = getelementptr float, ptr %ptr, i32 1
+ %ld0 = load float, ptr %ptr0
+ %ld1 = load float, ptr %ptr1
+ store float %ld0, ptr %ptr0
+ store float %ld1, ptr %ptr1
+ %user = fneg float %ld1
+ ret float %ld0
+}
+
|
| while (Change) { | ||
| Change = false; | ||
| for (Instruction *I : make_early_inc_range(DeadInstrCandidates)) { | ||
| if (I->hasNUses(0)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you traverse the instructions in the reverse order, you only need to do this once I believe. You can fix the order when you populate the set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to a single loop. I am sorting DeadInstrCandidates right before walking through it.
When scalars get replaced by vectors the original scalars may become dead. In that case erase them.
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/88/builds/4406 Here is the relevant piece of the build log for the reference |
When scalars get replaced by vectors the original scalars may become dead. In that case erase them.
When scalars get replaced by vectors the original scalars may become dead. In that case erase them.